package api

import (
	"fmt"
	"github.com/benji/software/Entities"
	"github.com/benji/software/common"
	"github.com/benji/software/service"
	"github.com/gin-gonic/gin"
	log "github.com/sirupsen/logrus"
	"net/http"
	"strconv"
	"strings"
)

func SignUp(c *gin.Context) {
	user := Entities.User{}
	if err := c.ShouldBind(&user); err != nil {
		log.Errorf("Fail to bind user,err: %v", err)
		c.JSON(http.StatusOK, Entities.ParameterErrorResponse)
		return
	}
	user.Password = common.Encrypt(user.Password)
	log.Infof("user-data:%v", user)
	if err := service.CreateUser(&user); err != nil {
		log.Errorf("Fail to create user ")
		c.JSON(http.StatusOK, Entities.GetBadResponse())
		return
	}
	log.Infof("user.ID :%v", user.ID)
	ss, err := common.GetJWTToken(user.Name, user.ID)
	if err != nil {
		log.Errorf("Fail to sign jwt token")
		c.JSON(http.StatusOK, Entities.JWTSignFailedRepsonse)
		return
	}
	c.Header("Authorization", fmt.Sprintf("Bearer %v", ss))
	c.JSON(http.StatusOK, Entities.GetSuccessResponse("注册成功"))
	return
}
func LoginStatus(c *gin.Context) {
	tokens := c.Request.Header["Authorization"]
	if len(tokens) == 0 {
		log.Errorf("Authorization header needed")
		c.JSON(http.StatusOK, gin.H{
			"login": false,
		})
	}
	token := tokens[0]
	log.Infof("token: %v", token)
	token = strings.Replace(token, "Bearer ", "", 1)
	log.Infof("token:%v", token)
	if len(token) == 0 {
		c.JSON(http.StatusOK, gin.H{
			"login": false,
		})
		return
	}
	_, err := common.ParseJWTToken(token)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusOK, gin.H{
			"login": false,
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"login": true,
	})
}
func Login(c *gin.Context) {
	type Login struct {
		Name     string `form:"name"`
		Password string `form:"password"`
	}
	login := Login{}
	if err := c.ShouldBind(&login); err != nil {
		log.Errorf("Fail to bind login data,err: %v", err)
		c.JSON(http.StatusOK, Entities.ParameterErrorResponse)
		return
	}
	login.Password = common.Encrypt(login.Password)
	log.Infof("user:%v,password: %v", login.Name, login.Password)
	res, ID := service.VerifyUser(login.Name, login.Password)
	if res == true {
		ss, err := common.GetJWTToken(login.Name, ID)
		if err != nil {
			log.Errorf("Fail to sign jwt token")
			c.JSON(http.StatusOK, Entities.JWTSignFailedRepsonse)
			return
		}
		log.Infof("ss:%v", ss)
		c.Writer.Header().Set("authorization", fmt.Sprintf("Bearer %v", ss))
		c.JSON(http.StatusOK, Entities.GetSuccessResponse("登陆成功"))
		return
	}
	c.JSON(http.StatusOK, Entities.VerifyFailedResponse)
}
func GetQuestions(c *gin.Context) {
	lstr := c.Query("level")
	level, err := strconv.ParseInt(lstr, 10, 64)
	if err != nil {
		log.Errorf("Fail to parse level to int, err: %v", err)
		c.JSON(http.StatusOK, Entities.GetResponse("Level is invalid", 1, ""))
		return
	}
	res, err := service.GetQuestions(level, common.QEUSTION_SIZE)
	if err != nil {
		log.Errorf("Fail to GetQuestions, err: %v", err)
		c.JSON(http.StatusOK, Entities.GetResponse("Fail to get questions", 2, ""))
		return
	}
	c.JSON(http.StatusOK, Entities.GetSuccessResponse(res))
}
func GetAnswer(c *gin.Context) {
	answers := Entities.StudentAnswers{}
	if err := c.ShouldBindJSON(&answers); err != nil {
		log.Errorf("Fail to bind questionIDs,err: %v", err)
		c.JSON(http.StatusOK, Entities.ParameterErrorResponse)
		return
	}
	res, err := service.GetAnswers(c, answers)
	if err != nil {
		log.Errorf("Fail to GetAnswers,err: %v", err)
		c.JSON(http.StatusOK, Entities.ServerErrorResponse)
		return
	}
	c.JSON(http.StatusOK, Entities.GetSuccessResponse(res))

}
func GetUserInfo(c *gin.Context) {
	id, ok := c.Value("id").(int)
	if !ok {
		log.Errorf("Fail to get studentID")
		c.JSON(http.StatusForbidden, Entities.VerifyFailedResponse)
		return
	}
	res, err := service.GetUserInfo(id)
	if err != nil {
		log.Errorf("Fail to get user info ,err: %v", err)
		c.JSON(http.StatusOK, Entities.ServerErrorResponse)
		return
	}
	c.JSON(http.StatusOK, res)
}

func UpdateUserInfo(c *gin.Context) {

}

func GetUserScore(c *gin.Context) {
	id, ok := c.Value("id").(int)
	if !ok {
		log.Errorf("Fail to get studentID")
		c.JSON(http.StatusForbidden, Entities.VerifyFailedResponse)
		return
	}
	scores, err := service.GetUserScore(id)
	if err != nil {
		log.Errorf("Fail to GetUserScore, err:%v", err)
		c.JSON(http.StatusOK, Entities.ServerErrorResponse)
		return
	}
	c.JSON(http.StatusOK, Entities.GetSuccessResponse(scores))
	return
}
func GetAllHistory(c *gin.Context) {
	userID, ok := c.Value("id").(int)
	if !ok {
		log.Errorf("GetAllHistory: fail to get userID")
		c.AbortWithStatusJSON(http.StatusForbidden, Entities.ParameterErrorResponse)
		return
	}
	data, err := service.GetUserAllHistory(userID)
	if err != nil {
		log.Errorf("GetAllHistory: fail to get userID")
		c.AbortWithStatusJSON(http.StatusInternalServerError, Entities.ServerErrorResponse)
		return
	}
	c.JSON(http.StatusOK, Entities.GetSuccessResponse(data))
	return
}
func GetHistory(c *gin.Context) {
	history := c.Param("id")
	historyID, err := strconv.ParseInt(history, 10, 64)
	if err != nil {
		log.Errorf("Fail to parse history to int,err:%v", err)
		c.JSON(http.StatusOK, Entities.ParameterErrorResponse)
		return
	}
	res, err := service.GetHistory(int(historyID))
	if err != nil {
		log.Errorf("Fail to GetHistory,err:%v", err)
		c.JSON(http.StatusOK, Entities.ServerErrorResponse)
		return
	}
	c.JSON(http.StatusOK, Entities.GetSuccessResponse(res))

}
